﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using FRAFV.Common;

namespace FRAFV.Common.Localization
{
	public struct Label: IKeyItem<string, string>
	{
		private CultureInfo language;
		private string text;

		public CultureInfo Language { get { return this.language; } }
		public string Text { get { return this.text; } set { this.text = value.EmptyIfNull(); } }
		string IKeyItem<string, string>.Key { get { return ResolveLang(this.Language); } }
		string IKeyItem<string, string>.Value { get { return this.text; } set { this.Text = value; } }

		public Label(CultureInfo lang, string value)
		{
			language = lang;
			text = value;
		}

		public Label(string lang, string value)
		{
			text = value;
			language = ResolveLang(lang);
		}

		public static CultureInfo ResolveLang(string lang)
		{
			if (lang == null)
				return null;
			return CultureInfo.GetCultureInfo(lang);
		}

		public static string ResolveLang(CultureInfo lang)
		{
			if (lang == null)
				return null;
			return lang.TwoLetterISOLanguageName;
		}

		public bool Equals(Label label)
		{
			return label.Text == this.Text && ResolveLang(label.Language) == ResolveLang(this.Language);
		}

		public override bool Equals(object obj)
		{
			if (obj == null || !(obj is Label))
				return false;
			var label = (Label)obj;
			return label.Text == this.Text && ResolveLang(label.Language) == ResolveLang(this.Language);
		}

		public override int GetHashCode()
		{
			return this.Text.EmptyIfNull().GetHashCode() ^ ResolveLang(this.Language).EmptyIfNull().GetHashCode();
		}

		public override string ToString()
		{
			return this.Text;
		}
	}

	public class LocalizedLabel<TLabel>: KeyCollection<string, string, TLabel>
		where TLabel: IKeyItem<string, string>
	{
		protected virtual TLabel CreateValue(CultureInfo lang, string label)
		{
			return (TLabel)Activator.CreateInstance(typeof(TLabel), lang, label);
		}

		protected override TLabel CreateValue(string lang, string label)
		{
			return CreateValue(Label.ResolveLang(lang), label);
		}

		public string this[CultureInfo lang]
		{
			get
			{
				int k = IndexOf(Label.ResolveLang(lang));
				if (k >= 0)
					return base.items[k].Value;
				else
					return null;
			}
			set
			{
				SetValue(IndexOf(Label.ResolveLang(lang)), lang, value);
			}
		}

		public void Add(CultureInfo lang, string label)
		{
			this.items.Add(CreateValue(lang, label));
		}

		public bool Contains(CultureInfo lang)
		{
			return IndexOf(Label.ResolveLang(lang)) >= 0;
		}

		public bool ContainsLabel(string label)
		{
			return this.items.Any(item => item.Value == label);
		}

		public void Insert(int index, CultureInfo lang, string label)
		{
			this.items.Insert(index, CreateValue(lang, label));
		}

		public virtual bool Remove(CultureInfo lang)
		{
			return Remove(Label.ResolveLang(lang), false);
		}

		public virtual void SetValue(int index, CultureInfo lang, string value)
		{
			if (index >= 0 && index < base.items.Count)
			{
				var label = base.items[index];
				label.Value = value;
				base.items[index] = label;
			}
			else
				this.items.Add(CreateValue(lang, value));
		}
	}

	public class LocalizedLabel: LocalizedLabel<Label>
	{
		protected override bool Equals(ref Label label, string lang)
		{
			return Label.ResolveLang(label.Language) == lang;
		}

		protected override Label CreateValue(CultureInfo lang, string label)
		{
			return new Label(lang, label);
		}
	}
}
